import os
import subprocess

# import loguru
from log_config import logger

from cmake import CmakeDepends
import re
from ruamel import yaml
import mantiDB



def find_file(library_name, prefix, suffix, search_paths):

    """
    查找指定库的文件，具有特定的前后缀。

    参数：
    - library_name (str): 需要查找的库名称。
    - prefix (str): 文件的前缀，例如 "Find"。
    - suffix (str): 文件的后缀，例如 ".cmake"。
    - search_paths (list): 需要搜索的基路径列表。

    返回：
    - str: 找到的文件的完整路径，如果未找到则返回 None。
    """
    # 遍历每个基路径
    for base_path in search_paths:
        # 使用 os.walk 遍历目录树
        for root, dirs, files in os.walk(base_path):
            for file in files:
                # 检查文件名是否匹配指定的前缀、库名称和后缀
                if file.lower() == f'{prefix}{library_name}{suffix}'.lower():
                    # 找到匹配的文件，返回完整路径
                    return os.path.join(root, file)
    # 如果未找到任何匹配的文件，返回 None
    return None


# 返回 CmakeDepends
# 应该不存在类似find_package去递归找文件的情况，但是暂时留着
# def ProcessConfig(config_path):
#     cmake = CmakeDepends()
#     if config_path:
#         cmake.parse(config_path)
#         directory, filename = os.path.split(config_path)
#         VAR_MAP = {'QT_MAJOR_VERSION': ['5', '6']}
#         loguru.logger.info(f"Processing File {config_path} ......")
#         cmake.save_only_depends(directory, VAR_MAP, f"{filename}-mid-depends.yaml")
#     return cmake
#
# def ProcessVersion(version_path):
#     # 根据VersionConfig.cmake提取版本号，无用
#     try:
#         with open(version_path, 'r') as file:
#             for line in file:
#                 if 'set(PACKAGE_VERSION' in line:
#                     # 使用正则表达式匹配版本号
#                     match = re.search(r'set\(PACKAGE_VERSION\s+(.*)\)', line)
#                     if match:
#                         version = match.group(1).strip("'\" ")
#                         return version
#     except Exception:
#         # print(f"文件 '{version_path}' 不存在或无法访问")
#         pass
#     return 'unknown'  # 如果未找到版本信息失效




class AutotoolOrderProcessor:
    def __init__(self,working_dir, os_version, config_cmake_path = "/usr/lib64/cmake",module_cmake_path = "/usr/share/cmake/Modules"):
        # Module 模式
        # self.module_prefix = 'Find'
        # self.module_suffix = '.cmake'
        # Config 模式
        # self.config_prefix1 = ''
        # self.config_suffix1 = 'Config.cmake'
        # self.config_prefix2 = ''
        # self.config_suffix2 = '-config.cmake'
        # self.version_suffix = 'ConfigVersion.cmake'
        # self.find_package_search_paths = [
        #     config_cmake_path,  # Config 模式下，欧拉系统中的路径
        #     module_cmake_path,  # Module 模式下，欧拉系统中的路径
        #     working_dir,   # Some projects have extra cmake files
        #     'package-mapping-test\\cmake',  # Config 模式，在WIN中测试用
        #     'package-mapping-test\\Modules'  # Module 模式，在WIN中测试用
        # ]
        # 访问数组，用来加速
        self.visited = set()
        self.result = {}
        self.os_version = os_version
        # mantiDB.save_data(self.os_version)




    # 返回: 依赖信息, 版本号
    # def ProcessFiles(self, lib_name, config_path):
    #     # 处理VersionConfig.cmake
    #     # version = ProcessVersion(version_path)
    #     # 处理Config.cmake
    #     cmake = ProcessConfig(config_path)
    #     return cmake.libraries_dict

    # find_package、find_path、pkg_check_modules、find_library、target_link_libraries。
    # def process_find_package(self, pkg_name):
    #     # 处理 find_package 命令
    #     # 需要递归，生成新的依赖
    #     # 混合模式，先按照Config模式找，找不到，再按照Module模式找
    #     config_path = find_file(pkg_name, self.config_prefix1, self.config_suffix1, self.find_package_search_paths)
    #     if config_path is None:
    #         config_path = find_file(pkg_name, self.config_prefix2, self.config_suffix2, self.find_package_search_paths)
    #     if config_path is None:
    #         config_path = find_file(pkg_name, self.module_prefix, self.module_suffix, self.find_package_search_paths)
    #
    #     # version_path = find_file(pkg_name, self.version_suffix, self.find_package_search_paths)
    #     value = {}
    #     value["config_path"] = config_path
    #     # value["version_path"] = version_path
    #     value["depends_info"]= self.ProcessFiles(pkg_name, config_path)
    #     # 返回含有新依赖的字典（DEBUG用）：
    #     # value = {
    #     #     'config_path': config_path,
    #     #     'version_path': version_path,
    #     #     'depends_info': depends_info,
    #     #     'version_info': version_info
    #     # }
    #     # find_package.DtkCore无果，故在结果中加入pkgconfig(DtkCore)
    #     add_rpms, _ = self.process_pkg_check_modules(pkg_name)
    #     return (value,add_rpms) , True



    def process_headers(self, file_name):
        # 按空格分割
        name_list = file_name.split()
        rpms = set()
        for name in name_list:
            # 得去除夹杂的版本信息："ibus-1.0 >= 1.5.0" -> "ibus-1.0"
            name = name.split('>')[0].split('<')[0].split('=')[0]
            # 删除多余的引号和空格
            name = name.replace('"', '').replace("'", "").replace(" ", "").replace("]","").replace("[","")

            # 因为 name 可能会是 pulse/pulse.h 需要提取pulse.h 继而提取 pulse
            name = name.partition(".")[0]
            full_order = f"PROCESS_HEADER.{name}"
            if full_order not in self.visited:
                self.visited.add(full_order)
                rpms.update(mantiDB.search(name,".h",self.os_version))
                self.result[name] = rpms
            else:
                rpms.update(self.result[name])

        # 返回.h对应的rpm数组,无需递归
        # loguru.logger.info(f"find_path->{name}.h")
        # loguru.logger.info(f"get rpms:{rpms}")
        return rpms, False



    def process_modules(self,file_name):
        # 按空格分割
        name_list = file_name.split()
        rpms = set()
        for name in name_list:
            # 处理 modules 相关命令
            # pkg_check_modules.xxx  -> Just map to pkgconfig(xxx)
            name = os.path.basename(name)
            full_order = f"PROCESS_MODULE.{name}"
            if full_order not in self.visited:
                self.visited.add(full_order)
                rpms.update(mantiDB.search(name, ".pc",self.os_version))
                self.result[name] = rpms
            else:
                rpms.update(self.result[name])
            # 返回.pc对应的rpm数组,无需递归
            # loguru.logger.info(f"pkg_check_modules->{name}.pc or pkgconfig({name})")
            # loguru.logger.info(f"get rpms:{rpms}")
            # rpms.add(f"pkgconfig({name})")
        return rpms, False


    def process_libs(self, lib_names):
        # 处理 lib 相关命令
        # 按空格分割
        name_list = lib_names.split()
        rpms = set()
        for lib_name in name_list:
            name = lib_name.partition(".")[0]
            full_order = f"PROCESS_LIB.{name}"
            if full_order not in self.visited:
                self.visited.add(full_order)

                rpms.update(mantiDB.search(name, ".so",self.os_version))
                self.result[name] = rpms
            else:
                rpms.update(self.result[name])
            # 返回.a或.so对应的rpm数组,无需递归
            # loguru.logger.info(f"find_library->(lib){lib_name}.so or (lib){lib_name}.a")
            # loguru.logger.info(f"get rpms:{rpms}")
        return rpms, False

    def process_target_link_libraries(self, file_name):
        # 处理 target_link_libraries 命令
        # 去除冒号： Qt5::Core => Qt5Core 从而去找 libQt5Core.so
        file_name = file_name.replace(":", "")

        name = os.path.basename(file_name).partition(".")[0]
        full_order = f"pkg_target_link_libraries.{name}"
        if full_order not in self.visited:
            self.visited.add(full_order)
            rpms = mantiDB.search(name, ".so",self.os_version)
            self.result[name] = rpms
        else:
            rpms = self.result[name]
        # 返回.a或.so对应的rpm数组,无需递归
        # loguru.logger.info(f"target_link_libraries->(lib){file_name}.so or (lib){file_name}.a")
        # loguru.logger.info(f"get rpms:{rpms}")
        return rpms, False

    def process_files(self, file_names):
        # 处理 files 相关命令
        # 处理 lib 相关命令
        # 按空格分割
        name_list = file_names.split()
        rpms = set()
        for file_name in name_list:
            name = file_name.partition(".")[0]
            full_order = f"PROCESS_FILE.{name}"

            if full_order not in self.visited:
                self.visited.add(full_order)
                rpms.update(mantiDB.search(name, ".h",self.os_version))
                # if name == "DGraph":
                #     print(f"find:{rpms}")
                self.result[name] = rpms
            else:
                rpms.update(self.result[name])
            # loguru.logger.info(f"process_find_program->{name}")
            # loguru.logger.info(f"get rpms:{rpms}")
        return rpms, False

    def process_programs(self, program_names):
        # 处理 programs 相关命令
        # 按空格分割
        name_list = program_names.split()
        rpms = set()
        for program_name in name_list:
            name = os.path.basename(program_name).partition(".")[0]
            if name.startswith("'") and name.endswith("'"):
                name = name[1:-1]
            full_order = f"PROCESS_PROGRAM.{name}"

            if full_order not in self.visited:
                self.visited.add(full_order)
                rpms.update(mantiDB.search(name, "program",self.os_version))

                # if name == "DGraph":
                #     print(f"find:{rpms}")
                self.result[name] = rpms
            else:
                rpms.update(self.result[name])
            # loguru.logger.info(f"process_find_program->{name}")
            # loguru.logger.info(f"get rpms:{rpms}")
        return rpms, False

    def process_tools(self, tool_names):
        # 处理 tools 相关命令
        # 按空格分割
        name_list = tool_names.split()
        rpms = set()
        for tool_name in name_list:
            name = os.path.basename(tool_name).partition(".")[0]
            name = name.replace('"','').replace("'",'')
            full_order = f"PROCESS_PROGRAM.{name}"

            if full_order not in self.visited:
                self.visited.add(full_order)
                rpms.update(mantiDB.search(name, "program",self.os_version))
                # if name == "DGraph":
                #     print(f"find:{rpms}")
                self.result[name] = rpms
            else:
                rpms.update(self.result[name])
            # loguru.logger.info(f"process_find_program->{name}")
            # loguru.logger.info(f"get rpms:{rpms}")
        return rpms, False

    def process(self, order):
        order_name, _, pkg_or_file_name = order.partition('.')

        # 注意 pkg_or_file_name 可能是多个 n1 n2 n3 ... nn  以空格分开
        # 得去除夹杂的版本信息："ibus-1.0 >= 1.5.0" -> "ibus-1.0"
        pkg_or_file_name = pkg_or_file_name.split('>')[0].split('<')[0].split('=')[0]
        # 删除多余的引号和空格
        # pkg_or_file_name = pkg_or_file_name.replace('"', '').replace("'", "").replace(" ","")
        pkg_or_file_name = pkg_or_file_name.replace('"', '').replace("'", "")
        # print(pkg_or_file_name)
        rpms = []
        add_rpms = set()
        need_recursion = False
        # print("order:", order)
        # print("pkg_or_file_name", pkg_or_file_name)
        # print("order_name:", order_name)
        if 'AC_CHECK_HEADERS_ONCE' in order_name or 'AC_CHECK_HEADER' in order_name or 'AC_CHECK_HEADERS' in order_name:
            add_rpms, need_recursion = self.process_headers(pkg_or_file_name)
        elif 'AC_CHECK_FILE' in order_name or 'AC_CHECK_FILES' in order_name:
            add_rpms, need_recursion = self.process_files(pkg_or_file_name)
        elif 'AC_CHECK_LIB' in order_name or 'AC_SEARCH_LIBS' in order_name:
            add_rpms, need_recursion = self.process_libs(pkg_or_file_name)
        elif 'PKG_CHECK_MODULES' in order_name or 'PKG_CHECK_EXISTS' in order_name:
            add_rpms, need_recursion = self.process_modules(pkg_or_file_name)
        elif 'AC_CHECK_PROGS' in order_name or 'AC_CHECK_PROG' in order_name or 'AC_PATH_PROGS_FEATURE_CHECK' in order_name or 'AC_PATH_PROGS' in order_name or 'AC_PATH_PROG' in order_name:
            '''

            nager-openconnect-1.2.8/autotool_output/macros.yaml:4:AC_CHECK_PROG.has_file:
            NetworkManager-openconnect/NetworkManager-openconnect-1.2.8/autotool_output/macros.yaml:9:AC_CHECK_PROG.has_find:
            NetworkManager-openconnect/NetworkManager-openconnect-1.2.8/macros.yaml:4:AC_CHECK_PROG.has_file:
            NetworkManager-openconnect/NetworkManager-openconnect-1.2.8/macros.yaml:9:AC_CHECK_PROG.has_find:
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/autotool_output/depends.yaml:11:  AC_CHECK_PROG.has_file:
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/autotool_output/depends.yaml:16:  AC_CHECK_PROG.has_find:
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/autotool_output/final_depends.yaml:6:- AC_CHECK_PROG.file
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/autotool_output/final_depends.yaml:8:- AC_CHECK_PROG.find
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/autotool_output/macros.yaml:4:AC_CHECK_PROG.has_file:
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/autotool_output/macros.yaml:9:AC_CHECK_PROG.has_find:
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/macros.yaml:4:AC_CHECK_PROG.has_file:
            NetworkManager-openvpn/NetworkManager-openvpn-1.10.2/macros.yaml:9:AC_CHECK_PROG.has_find:
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/autotool_output/depends.yaml:11:  AC_CHECK_PROG.has_file:
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/autotool_output/depends.yaml:16:  AC_CHECK_PROG.has_find:
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/autotool_output/final_depends.yaml:4:- AC_CHECK_PROG.file
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/autotool_output/final_depends.yaml:9:- AC_CHECK_PROG.find
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/autotool_output/macros.yaml:4:AC_CHECK_PROG.has_file:
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/autotool_output/macros.yaml:9:AC_CHECK_PROG.has_find:
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/macros.yaml:4:AC_CHECK_PROG.has_file:
            NetworkManager-pptp/NetworkManager-pptp-1.2.8/macros.yaml:9:AC_CHECK_PROG.has_find:
            NetworkManager-vpnc/NetworkManager-vpnc-1.2.8/autotool_output/depends.yaml:11:  AC_CHECK_PROG.has_file:
            NetworkManager-vpnc/NetworkManager-vpnc-1.2.8/autotool_output/depends.yaml:16:  AC_CHECK_PROG.has_find:
            NetworkManager-vpnc/NetworkManager-vpnc-1.2.8/autotool_output/final_depends.yaml:4:- AC_CHECK_PROG.file
            '''

            add_rpms, need_recursion = self.process_programs(pkg_or_file_name)
        elif 'AC_PATH_TOOL' in order_name or 'AC_PATH_TARGET_TOOL' in order_name or 'AC_CHECK_TOOL' in order_name or 'AC_CHECK_TOOLS' in order_name or 'AC_CHECK_TARGET_TOOL' in order_name or 'AC_CHECK_TARGET_TOOLS' in order_name:
            # print(order)
            add_rpms, need_recursion = self.process_tools(pkg_or_file_name)
        else:
            #TODO: show warning here
            logger.warning(f'cannot match any order. order:{order}, order_name:{order_name}, pkg_or_file_name:{pkg_or_file_name}')
            pass
        #TODO: warn and show debug info, if add_rpms is empty
        if len(add_rpms) == 0:
            logger.debug(f'add_rpms for autotools is empty, order:{order}, order_name:{order_name}, pkg_or_file_name:{pkg_or_file_name}')
        rpms += list(add_rpms)
        return rpms, need_recursion

    def clear_result(self):
        self.visited.clear()
        self.result.clear()


